/*
 * $Id: CharacterOutputStreamLogRecordWriter.java 37 2012-12-28 09:15:03Z vladimirow@mail.ru $
 * $HeadURL: http://ultralog.googlecode.com/svn/ultralog/tags/release-20130123/src/java/com/google/code/ultralog/writer/CharacterOutputStreamLogRecordWriter.java $
 *
 * This file is a part of ultralog project (http://code.google.com/p/ultralog/).
 * Released under New BSD License.
 */
package com.google.code.ultralog.writer;

import com.google.code.ultralog.utils.CharacterOutputStream;
import com.google.code.ultralog.utils.CharacterSequenceBuilder;

/**
 * An implementation of {@link LogRecordWriter} interface that writes log
 * records into given character output stream formatting them using given
 * log record formatter.
 *
 * @author Mikhail Vladimirov
 */
public class CharacterOutputStreamLogRecordWriter implements LogRecordWriter
{
    private final static ThreadLocal <MyLogRecord> LOG_RECORD =
        new ThreadLocal <MyLogRecord> ();

    private final CharacterOutputStream output;
    private final LogRecordFormatter logRecordFormatter;

    /**
     * Create new log record writer that writes log records into given
     * character output stream formatting them using given log record formatter.
     *
     * @param output character output stream to write log records to
     * @param logRecordFormatter log record formatter to use for formatting log
     *        records
     */
    public CharacterOutputStreamLogRecordWriter (
        CharacterOutputStream output,
        LogRecordFormatter logRecordFormatter)
    {
        if (output == null)
            throw new IllegalArgumentException ("Output is null");

        if (logRecordFormatter == null)
            throw new IllegalArgumentException ("Log record formatter is null");

        this.output = output;
        this.logRecordFormatter = logRecordFormatter;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public LogRecord beginLogRecord (String loggerName, int level,
        String levelName)
    {
        MyLogRecord logRecord = LOG_RECORD.get ();
        LOG_RECORD.set (null);
        if (logRecord == null)
            logRecord = new MyLogRecord ();

        return logRecord.initialize (loggerName, level, levelName);
    }

    private class MyLogRecord
        extends CharacterSequenceBuilder implements LogRecord
    {
        private String loggerName;
        private int level;
        private String levelName;

        public MyLogRecord initialize (
            String loggerName, int level, String levelName)
        {
            if (loggerName == null)
                throw new IllegalArgumentException ("Logger name is null");

            if (levelName == null)
                throw new IllegalArgumentException ("Level name is null");

            this.loggerName = loggerName;
            this.level = level;
            this.levelName = levelName;

            return this;
        }

        @Override
        public void write ()
        {
            logRecordFormatter.formatLogRecord (
                loggerName, level, levelName, this, output);

            output.flush ();

            release ();
        }

        @Override
        public void cancel ()
        {
            release ();
        }

        private void release ()
        {
            reset ();
            LOG_RECORD.set (this);
        }
    }
}
